import java.io.PrintWriter;

public class Algorithm extends Setup {
	static int START = 1082;

	public static void main(String[] args) {
		init();

		long time = System.currentTimeMillis();
		loop();
		System.out.println(System.currentTimeMillis() - time);
	}

	public static void init() {
		setup();

		long time = System.currentTimeMillis();
		System.out.println("sortng users:");
		for (User u : USERA) {
			u.sort();
		}
		System.out.println(System.currentTimeMillis() - time);

	}

	static void loop() {
		System.out.println("run: ");
		double sumErr1 = 0;
		double sumErr2 = 0;
		int n = 0;

		PrintWriter pw = pw();

		/**
		 * RALLELIZE ME PLEASE!<br>
		 * thread 000: loop counter @ 000000, 0000999;<br>
		 * thread 001: loop counter @ 001000, 0001999;<br>
		 * thread 999: loop counter @ 999000, 1000000;<br>
		 */
		for (int userID = START; userID < USERB.length; userID++) {
			User outputUser = USERB[userID];
			for (int i = 0; i < outputUser.ilen; i++) {
				long start;
				long time;

				int itemID = outputUser.items[i];
				byte vote = outputUser.votes[i];
				n++;
				System.out.printf("%7d %7d %4d      ", userID, itemID, vote);

				start = System.currentTimeMillis();
				byte pred1 = alg_userSimple(userID, itemID);
				time = System.currentTimeMillis() - start;

				double err1 = vote - pred1;
				double sqe1 = err1 * err1;
				sumErr1 += sqe1;
				System.out.printf("%7d ", time);
				System.out.printf("%7d ", pred1);
				System.out.printf("%+5.0f   ", err1);
				System.out.printf("%05.3f   \t", Math.sqrt(sumErr1 / n));

				start = System.currentTimeMillis();
				byte pred2 = alg_userSimple2(userID, itemID);
				time = System.currentTimeMillis() - start;

				double err2 = vote - pred2;
				double sqe2 = err2 * err2;
				sumErr2 += sqe2;
				System.out.printf("%7d ", time);
				System.out.printf("%7d ", pred2);
				System.out.printf("%+5.0f   ", err2);
				System.out.printf("%05.3f   \n", Math.sqrt(sumErr2 / n));

				pw.print(pred1);
				pw.print(",");
				pw.print(pred2);
				pw.print(",");
				pw.println(vote);
				pw.flush();
			}
		}

		pw.close();
	}

	static byte alg_userSimple(int inputUserID, int inputItemID) {
		double tot = 700;
		int hit = 10;
		User inputUser = USERA[inputUserID];

		for (int historyItemID : inputUser.items) {
			Item historyItem = ITEMA[historyItemID];

			for (int linkedUserID : historyItem.users) {
				User linkedUser = USERA[linkedUserID];

				byte vote = linkedUser.getVote(inputItemID);
				if (vote > -1) {
					tot += vote;
					hit++;
				}
			}
		}

		return (byte) (tot / hit);
	}

	static byte alg_userSimple2(int inputUserID, int inputItemID) {
		double tot = 700;
		int hit = 10;
		User inputUser = USERA[inputUserID];

		for (int historyItemID : inputUser.items) {
			Item historyItem = ITEMA[historyItemID];

			for (int linkedUserID : historyItem.users) {
				User linkedUser = USERA[linkedUserID];

				byte vote = linkedUser.voteGet(inputItemID);
				if (vote > -1) {
					tot += vote;
					hit++;
				}
			}
		}

		return (byte) (tot / hit);
	}

	static byte alg_itemSimple(int inputUserID, int inputItemID) {
		double tot = 700;
		int hit = 10;
		Item inputItem = ITEMA[inputItemID];

		for (int historyUserID : inputItem.users) {
			User historyUser = USERA[historyUserID];

			for (int linkedItemID : historyUser.items) {
				Item linkedItem = ITEMA[linkedItemID];

				byte vote = linkedItem.getVote(inputUserID);
				if (vote > -1) {
					tot += vote;
					hit++;
				}
			}
		}

		return (byte) (tot / hit);
	}

	static PrintWriter pw() {
		try {
			PrintWriter pw = new PrintWriter(START + "pred.txt");
			return pw;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
